/**
 * 该模块定义了一些线程操作。
 * License: BSD
 * Authors: Lucifer (786325481@QQ.com)
 * Copyright: Copyright (C) 2008 Lucifer. All rights reserved.
 */
module system.threading.ThreadUtility;

import platform.PAL;

/**
 * 将当前线程阻塞指定的毫秒数。
 * Params: milliseconds -> 线程被阻塞的毫秒数。
 *                         指定零 (0) 以指示应挂起此线程以使其他等待线程能够执行。
 *                         指定 Infinite 以无限期阻止线程。
 * Comments: 线程不会按操作系统的计划在指定的时段内执行。
 *           在 Windows 平台上此方法不执行标准的 COM 和 SendMessage 消息泵处理。
 *           0 值会使线程放弃剩下的时间片。可以参考 yield 方法。
 */
public void sleep(uint milliseconds)
{
	version(Windows)
	{
		Sleep(milliseconds);
	}
	else
	{
		static assert(false, "Not supported for this platform yet.");
	}
}

/**
 * 它相当于 std.thread 中 Thread.yield 方法。
 * Comments: std.thread 中 Thread.yield 方法在 Windows 上
 *           的实现采用了 Sleep(0) ，并不高效，而且存在
 *           优先级反向问题。这里采用 SwitchToThread 方法。
 */
public void yield()
{
	version(Windows)
	{
		SwitchToThread();
	}
	else version(linux)
	{
		sched_yield();
	}
	else
	{
		static assert(false, "Not supported for this platform yet.");
	}
}

/**
 * 导致线程等待由 iterations 参数定义的时间量。
 *
 * Parmas: iterations -> 定义线程等待时间的 32 位有符号整数。
 *
 * Comments: spinWait 方法在实现锁定方面十分有用。
 *           spinWait 实质上会将处理器置于十分紧密的循环中，其循环计数由 iterations 参数指定。
 *           因此，等待的持续时间取决于处理器的速度。
 *
 *           针对这一点，将此方法与 sleep 方法进行对比。
 *           调用 sleep 的线程会放弃其处理器时间当前片断的剩余部分，
 *           即使指定的时间间隔为零也不例外。
 *           如果为 sleep 指定非零的时间间隔，则线程计划程序会不考虑该线程，直到该时间间隔结束。
 *           
 *           spinWait 并不广泛适用于普通应用程序。
 *
 *           Note: 在避免上下文切换可带来益处的极少数情况下（例如，当已知即将发生状态更改时），
 *                 应在循环中调用 spinWait 方法。
 *                 spinWait 执行的代码旨在防止可能在多处理器计算机上发生的问题。
 *                 例如，在具有多个采用 Hyper-Threading™ 技术的Intel™ 处理器的计算机上，
 *                 spinWait 可防止在某些情况下出现处理器占用不足的现象。
 * 
 *           spinWait很少被使用，它的作用是等待一个在极短时间（可能小于一微秒）内可准备好的可预期的资源，
 *           而不用调用sleep方法阻止线程而浪费CPU时间。不过，这种技术的优势只有在多处理器计算机：
 *           对单一处理器的电脑，直到轮询的线程结束了它的时间片之前,一个资源没有机会改变状态，这有违它的初衷。
 *           并且调用spinWait经常会花费较长的时间这本身就浪费了CPU时间。
 */
public void spinWait(int iterations)
{
    for(auto i = 0; i < iterations; i++)
    {
        yieldProcessor();
    }
}

/*
 * 用于处理超线程CPU问题。
 * Comments: 在 x86 平台上，它等效于汇编指令 PAUSE 。
 *           但其可以兼容早期未支持超线程技术的 IA-32 CPU 。
 */
private void yieldProcessor()
{
    version(D_InlineAsm_X86)
    {
        asm
        {
            rep;
			nop;
        }
    }
}
